Организация памяти.

V1.0


  1. Понятия и термины.

    Окно паямяти (memory window) – область адресного пространства памяти процессора. Все адресное пространство (0x0000-0xFFFF) поделено на 4 окна по 16Kбайт. Окна имеют номера 0, 1, 2, 3.

          Таблица 1.1

          Начальные адреса окон памяти

          Окна

          Занимаемые адреса

          0

          0x0000-0x3FFF

          1

          0x4000-0x7FFF

          2

          0x8000-0xBFFF

          3

          0xC000-0xFFFF

    Странца паямяти (memory page) – область памяти размером 16К, которая может быть подключена (впечатана) в одно из окон памяти процессора.

    Куча – область памяти, имеющая определенную структуру, которая позволяет выделять и освобождать участки памяти произвольной длины по запросу приложений. Существуют два типа куч - локальная куча и глобальная куча. Максимальная длина выделяемого блока памяти ограничена размером страницы (16К).

    Локальная куча – размер локальной кучи ограничен размером страницы. Локальная куча всегда целиком помещается на странице. Адресация в пределах локальной кучи производится с помощью коротких указателей типа sptr.

    Глобальная куча – объединяет все локальные кучи в системе в единую. Размер глобальной кучи ограничен размером свободной (то есть не занятой под системные нужды) памяти. Адресация в пределах глобальной кучи производится с помощью длинных указателей типа lptr.

  2. Назначение окон памяти.

    При работе под управлением операционной системы каждое окно имеет свое назначение.

    0е окно(окно ядра) предназначено для размещения кода ядра ОС. Окно может временно быть занято страницей с программой пользователя (используется в основном для эмуляции стандартных 48х-128х), но в этом случае необходимо, чтобы при возврате в ОС обеспечивалось впечатывание в это окно страницы, содежащей ядро ОС.

    1е окно(окно системных переменных) предназначено для хранения всех системных переменных и системной кучи. Окно может временно быть занято страницей с программой пользователя (используется в основном для эмуляции стандартных 48х-128х), но перед запуском программы пользователя его содержимое должно быть сохранено на теневой странице. После возврата в ОС содержимое окна должно быть восстановлено с теневой страницы. Функции сохранения-восстановления окна возложены на ОС.

    2е окно (временное окно) предназначено для межпрограммного обмена и обмена пользовательской программы с динамической памятью. При преобразовании длинного указателя в короткий пользователской программе возвращается короткий указатель на окно памяти номер 2.

    3е окно(окно пользователя) предназначено для приложений пользователя и библиотек.

  3. Логическая организация страниц.

    Система хранит массив описателей атрибутов страниц. Атрибут страницы – 16битное целое число. Значения атрибутов:

    Биты 0,1 - номер окна памяти (0,1,2,3), в которое подключается страница для работы c ней.

    Эти биты определяют в какое из окон памяти должна включаться страница для того, чтобы программа уровня пользователя могла корректно с ней работать, если на ней содержится нерелоцируемый код. См. таблицу 3.1.

    #define fWINMEM0 0x0001

    #define fWINMEM1 0x0002

    Таблица 3.1

    fWINMEM1

    fWINMEM0

    окна

    0

    0

    0

    0

    1

    1

    1

    0

    2

    1

    1

    3

    Страница занята. (бит 2)

    Если флаг установлен - то страница выделена приложению. Приложение само определяет размещение данных на странице произвольным образом (при сброшенном флаге fPAGE_LOC_HEAP) или страница имеет структуру типа локальной кучи (при установленном флаге fPAGE_LOC_HEAP). Программа может использовать всю страницу целиком (например для эмуляции 48Кмашины надо иметь 3 страницы, для эмуляции 128к - 8 страниц).

    Если флаг сброшен, то страница свободна.

    #define fPAGE_BUSY 0x0004

    На странице имеется локальная куча. (бит 3)

    Если флаг установлен, то страница имеет структуру типа локальной кучи. Локальная куча на на странице имеет следующий формат (за исключением основной системной кучи):

    0000 Смещение от начала страницы 3FFF

    Описатель кучи

    Описатель 0го эл-та

    Данные 0го эл-та

    ...

    Описатель Nго эл-та

    Данные 0го эл-та

    sizeof(sLOCHEAP)

    sizeof(sLOCHEAP_BLK)

    NNN

    ...

    sizeof(sLOCHEAP_BLK)

    MMM

    Основная системная куча расположена расположена на одной странице с системными переменными и занимает только часть страницы. Описатель основной системной кучи определяется как системная переменная sLOCHEAP SYSGLOBALHEAP.

    #define fPAGE_LOC_HEAP 0x0008

    Страница занята системой. (бит 4)

    На такой странице не может быть организована локальная куча по запросу памяти от программы пользователя, но может быть организована дополнительная системная локальная куча. Однако, программа пользователя может занимать эту страницу (например в режиме эмуляции стандартых 48К и 128К). В этом случае системная страница копируется на другую системную страницу (кэш-страницу), затем на системную страницу копируется программа пользователя и выполняется. По завершении выполнения программы или ее остановке, кэш-страница копируется обратно на системную страницу.

    На системах, где в окно, содержащее страницу с системными переменными, можно впечатать произвольную страницу кэш-страница не используется, копирование не производится, в окно непосредственно впечатывается нужная страница.

    При установленном флаге fPAGE_SYS, флаг также установлен fPAGE_BUSY. Страница имеет структуру типа локальной кучи при установленном флаге fPAGE_LOC_HEAP.

    #define fPAGE_SYS 0x0010

    Кэш-страница. (бит 5)

    Страница занята под кэш системы. Этот флаг показывает, что на странице сохраняется состояние системы, когда программа пользователя использует окно, содержащее страницу с системными переменными. Флаг fPAGE_SCACHE используется только совместно с включенными флагами (fPAGE_SYS | fPAGE_BUSY). На системах, где в окно, содержащее страницу с системными переменными, можно впечатать произвольную страницу кэш-страница не используется. В системе используется не более одной кэш-страницы. Номер кэш-страницы есть константа для данной системы, поскольку система после возврата из программы, занимающей все адресное пространство процессора не в состоянии узнать, на какой именно странице расположена копия системных переменных.

    #define fPAGE_SCACHE 0x0020

    Нерелоцируемая страница. (бит 6)

    Если флаг установлен, то страница может использоваться только в окне, номер которого определяется полем fWINMEM0, fWINMEM1. Страницы, содержащие системные переменные и ядро ОС или исполняемый код пользователя – всегда нерелоцируемы.

    #define fPAGE_NORELOC 0x0040

    В таблице 3.2 представлены различные комбинации флагов, соответствующие разными типам страниц.

    Таблица 3.2

    Тип страницы

    Установленные флаги

    Свободная страница. ftPAGE_FREE

    Все флаги сброшены.

    Системная страница, содержащая ядро ОС или системные переменные ftPAGE_SYSOS

    fPAGE_SYS | PAGE_BUSY |

    fPAGE_NORELOC

    Системная куча (дополнительная) ftPAGE_SYSHEAP

    fPAGE_SYS | PAGE_BUSY |

    fPAGE_LOC_HEAP

    Страница системного кэша ftPAGE_SYSCACHE

    fPAGE_SYS | PAGE_BUSY |

    fPAGE_SCACHE | fPAGE_NORELOC

    Страница во временном окне памяти, если оно фиксировано ftPAGE_TEMPFIX

    fPAGE_SYS | PAGE_BUSY

    Пользовательская страница 16К ftPAGE_USER

    PAGE_BUSY

    Пользовательская локальная куча ftPAGE_USERHEAP

    PAGE_BUSY | fPAGE_LOC_HEAP

    Страница, содержащая исполняемый код пользователя ftPAGE_USERCODE

    PAGE_BUSY | fPAGE_NORELOC

  4. Логическая организация окон памяти.

    Для каждого окна памяти система хранит описатель типа sMEMWINFO.

    typedef struct

    {unsigned int flags; // Флаги управления окном памяти

    unsigned long page; // Номер страницы в окне

    unsigned long rpage; // Номер страницы, содержимое которой в данный момент

    // находится в окне

    } sMEMWINFO;

    Значения битов в поле flags приведены ниже.

    Фиксированное окно памяти.

    Если флаг установлен, в окне всегда впечатана страница page. Другая впечатана быть не может (Например страницы 5 и 2 всегда впечатаны в окна 1 и 2 соответственно в стандартном 128К). Если окно, содержащее системные переменные, определено как фиксированное, то поле rpage этого окна загружается номером кэш-страницы.

    Если в фиксированное окно памяти необходимо подключить произвольную страницу, то система делает следующее:

    - Если флаг флаг fWIN_NODEF для этого окна сброшен, то содержимое окна копируется на страницу rpage.

    - Копирует содержимое подключаемой страницы в это окно.

    - Запоминает номер подключаемой страницы в поле rpage.

    - Сбрасывает флаг fWIN_NODEF для этого окна.

    #define fWIN_FIXED 0x0001

    Окно памяти ПЗУ.

    Если флаг установлен, в окно впечатана страница ПЗУ, номер page.

    #define fWIN_ROM 0x0002

    Неопределенное окно памяти.

    Если флаг установлен, то номер впечатанной страницы неопределен. Например, этот атрибут устанавливается при инициализации системы для окна памяти номер 3 в стандартном 128К. Совместно включенные флаги (fWIN_FIXED | fWIN_NODEF) показывают, что данные из временного окна памяти не надо копировать на страницу rpage при впечатывании в это окно произвольной страницы. Такое значение флаги фиксированного окна памяти принимают после того, как страница фиксированного окна памяти rpage освобождается. Так же флаг fWIN_NODEF устанавливается при инициализации системы для временного окна памяти.

    #define fWIN_NODEF 0x0004

    В таблице 4.1 представлены различные комбинации флагов, соответствующие разными типам окон памяти.

    Таблица 4.1

    Тип страницы

    Установленные флаги

    Нефиксированная определенная страница ОЗУ

    Все флаги сброшены

    page– номер страницы, подключенной в окно

    Нефиксированная неопределенная страница ОЗУ

    fWIN_NODEF

    (окно 3 после инициализации системы)

    Фиксированная определенная страница ОЗУ

    fWIN_FIXED

    page– номер страницы, постоянно подключенной в окно

    rpage– номер страницы, копия которой находится в окне

    (окно 1 после инициализации системы)

    (окно 0 после инициализации системы, если система работает из ОЗУ)

    Фиксированная неопределенная страница ОЗУ

    fWIN_NODEF | fWIN_FIXED

    page– номер страницы, постоянно подключенной в окно

    (окно 2 после инициализации системы)

    Страница ПЗУ

    fWIN_ROM

    (окно 0 после инициализации системы, если система работает из ПЗУ)

  5. Функции работы с локальной кучей.

    Для работы с локальной кучей определены следующие структуры данных и константы.

    Константы для tLOCHEAP_BLK.flags

    #define fHEAPBLK_BUSY 0x0001 /* Блок занят */

    #define fHEAPBLK_LAST 0x0002 /* Блок последний */

    Описатель элемента кучи

    typedef struct

    {unsigned int size; // Размер элемента

    unsigned int flags; // Флаги

    }sLOCHEAP_BLK;

    Описатель кучи

    typedef struct

    {sLOCHEAP_BLK* firstel;// короткий указатель на первый элемент кучи

    sLOCHEAP_BLK* curel;// короткий указатель на первый текущий элемент кучи

    unsigned int size; // Максимальный размер данных в куче (0x0000-0x03FFF)

    }sLOCHEAP;

    С этими структурами работают три основные функции:

    tLOCHEAP* locheap_init(tLOCHEAP* heap, sptr adr, unsigned int size);

    Инициализирует кучу.

    heap - короткий указатель на структуру типа tLOCHEAP, куда пишутся данные о куче

    аdr - начальный адрес кучи (короткий указатель)

    size - размер кучи (Полный, то есть включая все описатели)

    Вся куча должна помещаться в одной странице (то есть должно выпоняться

    условие (adr & 0xC000) == ((adr+size) & 0xC000)

    Возвращает указатель на структуру tHEAP (то есть фактически heap)

    В случае неудачи возвращается NULL.

    sptr locmalloc(tLOCHEAP* hptr, unsigned int size);

    Резервирует память

    hptr - короткий указатель на описатель кучи

    size - размер запрашиваемого блока

    Возвращает указатель на зарезервированный блок или NULL, если нет места в куче

    void locfree(tHEAP* hptr, sptr* mem);

    Освобождает память в куче

    hptr - короткий указатель на описатель кучи

    mem - короткий указатель на освобождаемый блок памяти


  1. Функции работы со страницами.

    unsigned long get_pages();

    Выдает общее количество странц ОЗУ.

    unsigned long get_free_pages();

    Выдает общее количество свободных странц ОЗУ.

    signed int amempage(unsigned int win, unsigned int page);

    Впечатывает в запрошенное окно запрошенную страницу. Если окно фиксировано, то производит все процедуры, связанные с копированием.

    В случае ошибки возращает значение -EMEMWIN или -EMEMPAG

    В случае успешного выполнения возвращает EMEMOK

    lptr alloc_page(unsigned int flags);

    Ищет первую попавшуюся свободную страницу, объявляет ее как занятую, возвращает длинный указатель на нее. Если свободных страниц нет, возвращает NULL. Переменная flags определяет в каком режиме резервируется память на странице. Можно использовать следующие флаги:

    fWINMEM0, fWINMEM1 – номер окна для работы (при включенном fPAGE_NORELOC)

    fPAGE_SYS - системная страница.

    fPAGE_NORELOC – неперемещаемая страница.

    fPAGE_LOC_HEAP – на странице создается локальная куча.

    signed int free_page(lptr page) – освобождает странницу памяти, на которую указывает длинный указатель page. Если страница подключена в окно, то устанавливает флаг fWIN_NODEF для этого окна.

    В случае успеха возвращает EMEMOK, иначе -EMEMPAG. Не могут быть освобождены

    страницы, определенные как системная не имеющая структуры локальной кучи (страница, содержащая ядро ОС; страница, содержащая системные переменные; страница во временном окне памяти, если оно фиксировано; кэш-страница)

  2. Общие функции

    signed int mm_init();

    Инициализация менеджера памяти. Записывает начальные значения в массивы описателей окон памяти и страниц памяти. В случае успешного выполнения возвращает EMEMOK

  3. Указатели.

    Указатель – адрес памяти с которого начинается некий объект. Указатели бывают двух типов – короткий указатель типа sptr и длинный или абсобютный указатель типа lptr.

    Короткий указатель типа sptr – число размером 16 бит. Может указывать на пространство любого из 4х окон памяти. Применяется для указания на любую впечатанную в одно из окон страницу. Имеет следующий формат:

    Бит 15 Бит 14

    Бит 13 Бит 0

    Номер окна памяти

    Смещение от начала окна

    Длинный (абсолютный) указатель типа lptr – число размером 32 бита. Указывает на любой объект любой страницы. Имеет следующий формат:

    Бит 31 Бит 14

    Бит 13 Бит 0

    Номер страницы

    Смещение от начала страницы

    Все запросы от программ пользователя (то есть функции lptr malloc(int size) – выделить size байт, void free(lptr mem) - освободить память на которую указывает mem) и возвращаемые ими значения используют для адресации длинные указатели типа lptr. Перед тем, как пользовательская программа сможет работать с областью памяти, длинный указатель должен быть преобразован в короткий с помощью функции sptr ltos_ptr(lptr lp).

    Короткий указатель может быть преобразован в длинный с помощью процедуры lptr stol_ptr(sptr sp).

    Указатель (длинный или короткий), все биты которого имеют значение 0, является пустым указателем NULL.

  4. Механизм преобразования указателей.

    Преобразование указателей для программы пользователя осуществляется по следующим правилам:

    Длинный (абсолютный) указатель в короткий указатель :

    lptr lp; //длинный указатель

    sptr sp;// короткий указатель

    unsigned int page;

    page = lp >> 14; // Вычисляем номер страницы

    if(MEMWINFO[3].page==page)

    {// Указатель указывает на значение в той же странице,

    // где находится программа пользователя

    sp = (lptr & 0x3FFF) | 0xC000; // Старшие два бита – номер окна памяти – 3.

    }

    else

    {// Указатель указывает на значение в другой странице

    amempage(0x02, page); // Впечатываем страницу page в окно 2

    sp = (lptr & 0x3FFF) | 0x8000; // Старшие два бита – номер страницы – 2.

    }

    Короткий указатель в длинный (абсолютный) указатель :

    lptr lp; //длинный указатель

    sptr sp;// короткий указатель

    lp =((sptr)MEMWINFO[sp>>0x0E].page) << 0x0E | (sp & 0x3FFF);

  5. Правила сравнения указателей.

    Всегда сравнивать между собой можно только длинные указатели.

    Короткие указатели можно сравнивать только при условии, что они образованы от длинных указателей, указывающих на одну страницу (как правило – от одного длинного указателя).

  6. Правила работы с указателями.

    Нельзя работать одновременно с двумя длинными указателями. Единственное действие, которое можно выполнять с длинными указателями – сравнение.

    С короткми указателями можно работать одновременно только, если они образованы от длинных указателей, указывающих на одну страницу (как правило – от одного длинного указателя).

  7. Продолжение следует, помощи и КОНСТРУКТИВНАЯ критика – приветствуются.